﻿<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>gRPC HTTP API example</title>
    <link rel="stylesheet" href="/lib/bootstrap/dist/bootstrap.min.css" />
    <style type="text/css">
        .nav-tabs {
            margin-bottom: 1em;
        }
        .alert:empty {
            display:none;
        }
        code {
            margin-bottom: 1em;
        }
        .container {
            max-width: 720px;
        }
    </style>
</head>
<body>
    <div class="container">
        <main role="main" class="pb-3">
            <h1 class="display-4 mb-4 mt-2">gRPC HTTP API example</h1>
            <p>
                <a href="https://github.com/aspnet/AspLabs/tree/master/src/GrpcHttpApi" target="_blank">gRPC HTTP API</a> allows you call gRPC methods with familiar HTTP concepts:
            </p>
            <ul>
                <li>HTTP verbs</li>
                <li>URL parameter binding</li>
                <li>JSON requests/responses</li>
            </ul>
            <p>
                RESTful APIs for your ASP.NET Core gRPC services. No duplication!
            </p>
            <img src="/images/grpc-rest-logo.png" class="img-fluid mb-3" alt="gRPC loves REST" />
            <h5 class="mb-3">Try it now</h5>
            <nav>
                <div class="nav nav-tabs" id="nav-tab" role="tablist">
                    <a class="nav-item nav-link active" id="nav-get-tab" data-toggle="tab" href="#nav-get" role="tab" aria-controls="nav-get" aria-selected="true">GET</a>
                    <a class="nav-item nav-link" id="nav-post-tab" data-toggle="tab" href="#nav-post" role="tab" aria-controls="nav-post" aria-selected="false">POST</a>
                    <a class="nav-item nav-link" id="nav-swagger-tab" data-toggle="tab" href="#nav-swagger" role="tab" aria-controls="nav-swagger" aria-selected="false">Swagger</a>
                    <a class="nav-item nav-link" id="nav-source-tab" data-toggle="tab" href="#nav-source" role="tab" aria-controls="nav-source" aria-selected="false">View source</a>
                </div>
            </nav>
            <div class="tab-content" id="nav-tabContent">
                <div class="tab-pane fade show active" id="nav-get" role="tabpanel" aria-labelledby="nav-get-tab">
                    <form id="sendGet">
                        <p>
                            Send a GET request to the Greeter gRPC service. The name is sent as a URL parameter.
                        </p>
                        <div class="form-row align-items-center">
                            <div class="col-auto">
                                <label class="sr-only" for="inlineFormInput">Hello</label>
                                <input type="text" class="form-control mb-2" id="nameGet" placeholder="Hello" required>
                            </div>
                            <div class="col-auto">
                                <button type="submit" class="btn btn-primary mb-2">Send</button>
                            </div>
                        </div>
                    </form>
                    <div class="alert alert-success" role="alert" id="resultGet"></div>
                </div>
                <div class="tab-pane fade" id="nav-post" role="tabpanel" aria-labelledby="nav-post-tab">
                    <form id="sendPost">
                        <p>
                            Send a POST request to the Greeter gRPC service. JSON is sent in the request body.
                        </p>
                        <div class="form-row align-items-center">
                            <div class="col-auto">
                                <label class="sr-only" for="inlineFormInput">Hello</label>
                                <input type="text" class="form-control mb-2" id="toPost" placeholder="Hello">
                            </div>
                            <div class="col-auto">
                                <label class="sr-only" for="inlineFormInput">From</label>
                                <input type="text" class="form-control mb-2" id="fromPost" placeholder="From">
                            </div>
                            <div class="col-auto">
                                <button type="submit" class="btn btn-primary mb-2">Send</button>
                            </div>
                        </div>
                    </form>
                    <div class="alert alert-success" role="alert" id="resultPost"></div>
                </div>
                <div class="tab-pane fade" id="nav-swagger" role="tabpanel" aria-labelledby="nav-swagger-tab">
                    <p>
                        View OpenAPI schema generated by Swagger and send requests with Swagger UI.
                    </p>
                    <p>
                        <a href="/swagger" target="_blank">Open Swagger UI</a>
                    </p>
                </div>
                <div class="tab-pane fade" id="nav-source" role="tabpanel" aria-labelledby="nav-source-tab">
                    <p>
                        This website's source code on GitHub:
                    </p>
                    <ul>
                        <li><a href="https://github.com/aspnet/AspLabs/blob/master/src/GrpcHttpApi/sample/Proto/greet.proto" target="_blank">Proto/greet.proto</a> - Add <code>google.api.http</code> annotations to map HTTP calls to gRPC.</li>
                        <li><a href="https://github.com/aspnet/AspLabs/blob/master/src/GrpcHttpApi/sample/Server/Startup.cs" target="_blank">Server/Startup.cs</a> - Register gRPC HTTP API with <code>AddGrpcHttpApi()</code>.</li>
                        <li><a href="https://github.com/aspnet/AspLabs/blob/master/src/GrpcHttpApi/sample/Server/Services/GreeterService.cs" target="_blank">Server/Services/GreeterService.cs</a> - Unchanged. gRPC and REST from one service!</li>
                    </ul>
                    <p>
                        Find out more about using gRPC HTTP API <a href="https://github.com/aspnet/AspLabs/tree/master/src/GrpcHttpApi#usage">here</a>.
                    </p>
                </div>
            </div>
        </main>
    </div>
    <script type="text/javascript" src="/lib/jquery/dist/jquery.min.js"></script>
    <script type="text/javascript" src="/lib/bootstrap/dist/bootstrap.bundle.min.js"></script>
    <script type="text/javascript">
        var nameGetInput = document.getElementById('nameGet');
        var getForm = document.getElementById('sendGet');
        var resultGetText = document.getElementById('resultGet');

        getForm.addEventListener('submit', function (event) {
            if (getForm.checkValidity()) {
                resultGetText.innerHTML = '';

                var url = '/v1/greeter/' + encodeURIComponent(nameGetInput.value);
                fetch(url).then(function (response) {
                    response.text().then(function (data) {
                        resultGetText.innerHTML = `<h6>Request</h6>
<p><code>GET ${url}</code></p>
<h6>Response</h6>
<p><code>${htmlEscape(data)}</code></p>
<h6>Result</h6>
<p>${JSON.parse(data).message}</p>`;
                    });
                });
            }

            event.preventDefault();
            event.stopPropagation();
        }, false);

        var toPostInput = document.getElementById('toPost');
        var fromPostInput = document.getElementById('fromPost');
        var postForm = document.getElementById('sendPost');
        var resultPostText = document.getElementById('resultPost');

        postForm.addEventListener('submit', function (event) {
            resultPostText.innerHTML = '';

            var url = '/v1/greeter';
            var content = JSON.stringify({ name: toPostInput.value, from: fromPostInput.value });
            fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: content
            }).then(function (response) {
                response.text().then(function (data) {
                    resultPostText.innerHTML = `<h6>Request</h6>
<p><code>POST ${url} ${htmlEscape(content)}</code></p>
<h6>Response</h6>
<p><code>${htmlEscape(data)}</code></p>
<h6>Result</h6>
<p>${JSON.parse(data).message}</p>`;
                });
            });

            event.preventDefault();
            event.stopPropagation();
        }, false);

        function htmlEscape(str) {
            return String(str)
                .replace(/&/g, '&amp;')
                .replace(/'/g, '&quot;')
                .replace(/'/g, '&#39;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;');
        }
    </script>
</body>
</html>
